package com.blaze.framework.core.util.uitls;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Optional;

/**
 * Java8 日期处理
 *
 * @author create at by Zhou ZongBo on 2020/11/12.
 */

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class DateUtil {
    public static final String YMD_HMS_STR = "yyyy-MM-dd HH:mm:ss";
    /**
     * 日期时间转换器，
     */
    @Getter
    @AllArgsConstructor
    public static class Formatter {

        private final DateTimeFormatter dateTimeFormatter;
        private final String pattern;

        public Formatter(String format) {
            this.dateTimeFormatter = DateTimeFormatter.ofPattern(format);
            this.pattern = format;
        }

        public Optional<String> format(TemporalAccessor temporal) {
            return Optional.ofNullable(temporal).map(dateTimeFormatter::format);
        }

        public Optional<LocalDate> ofDate(String dateStr) {
            return Optional.ofNullable(dateStr)
                    .filter(DateUtil::isNotEmpty)
                    .map(o -> dateTimeFormatter.parse(o, LocalDate::from));
        }

        public Optional<LocalDateTime> ofDateTime(String dateTimeStr) {
            return Optional.ofNullable(dateTimeStr)
                    .filter(DateUtil::isNotEmpty)
                    .map(o -> dateTimeFormatter.parse(o, LocalDateTime::from));
        }

        public Optional<LocalTime> ofTime(String timeStr) {
            return Optional.ofNullable(timeStr)
                    .filter(DateUtil::isNotEmpty)
                    .map(o -> dateTimeFormatter.parse(o, LocalTime::from));
        }

        public Optional<YearMonth> ofYearMonth(String timeStr) {
            return Optional.ofNullable(timeStr)
                    .filter(DateUtil::isNotEmpty)
                    .map(o -> dateTimeFormatter.parse(o, YearMonth::from));
        }
    }

    /**
     * 格式[_格式]*[_备注]*
     * <p>注：YMD 代表 yyyy-MM-dd
     */
    public static final Formatter YMD = new Formatter("yyyy-MM-dd");
    public static final Formatter YMD_SHORT = new Formatter("yyyyMMdd");
    public static final Formatter YMD_ZH = new Formatter("yyyy年MM月dd日");
    public static final Formatter MD_ZH = new Formatter("M月d日");

    public static final Formatter YM = new Formatter("yyyy-MM");

    public static final Formatter YMD_HMS = new Formatter(YMD_HMS_STR);
    public static final Formatter YMD_T_HMS = new Formatter("yyyy-MM-dd'T'HH:mm:ss");
    public static final Formatter YMD_T_HMS_6S = new Formatter("yyyy-MM-dd'T'HH:mm:ss.SSSSSS");
    public static final Formatter YMD_HM = new Formatter("yyyy-MM-dd HH:mm");
    public static final Formatter YMD_HMS_SHORT = new Formatter("yyyyMMddHHmmss");
    public static final Formatter YMD_HMS_S_SHORT = new Formatter("yyyyMMddHHmmssSSS");
    public static final Formatter Y2MD_HMS_SHORT = new Formatter("yyMMddHHmmss");
    public static final Formatter Y2MD_HM_SHORT = new Formatter("yyMMddHHmm");
    public static final Formatter Y2MD_H_SHORT = new Formatter("yyMMddHH");
    public static final Formatter YMD_HMS_20 = new Formatter("yyMMddHHmmss");

    public static final Formatter HMS = new Formatter("HH:mm:ss");
    public static final Formatter HM = new Formatter("HHmm");
    public static final Formatter HMS_SHORT = new Formatter("HHmmss");

    private static boolean isNotEmpty(final CharSequence cs) {
        return !isEmpty(cs);
    }

    private static boolean isEmpty(final CharSequence cs) {
        return cs == null || cs.length() == 0;
    }
}
